#!/usr/bin/env node

// 此处使用esModule引入，package.json中需添加“type”字段 (type字段是否添加其实和node版本有关，详情见笔记:Node第一章概述)
// const { program } = require("commander"); // 使用commonjs方式引入则package.json中无需添加“type”
import { program } from "commander";
import download from "download-git-repo";
import inquirer from "inquirer";
import { exec } from "child_process";
import fs from "node:fs";
import ora from "ora";

// 判断创建的文件是否已存在当前文件夹中
const isExist = (path) => {
  return fs.existsSync(path);
};
// 封装命令
const execCommand = (command, options, type) => {
  return new Promise((resolve, reject) => {
    // 开启子进程执行命令
    const childProcess = exec(command, options, (error, stdout, stderr) => {
      if (error) {
        reject({
          errorReason: error,
          errorType: type,
        });
      }
      resolve(stdout);
    });
    childProcess.stdout.pipe(process.stdout);
    // childProcess.stderr.pipe(process.stderr);
  });
};

// 封装clone方法
const createProjectAction = async (projectName, isTs) => {
  const branch = isTs ? "master" : "master"; // 暂无ts分支，统一都用master
  const gitPath = `direct:https://gitee.com/wuhun1990/vite-project.git#${branch}`; //direct代表侦测  根据传来的数据选择分支，如ts/js/master分支
  // 创建动画
  const spinner = ora("正在创建项目...");
  const installModules = ora("node_modules安装中...");
  const typeData = {
    create: { type: "spinner", desc: "项目创建" },
    install: { type: "installModules", desc: "node_modules安装" },
    run: { type: "runProject", desc: "运行项目" },
  };
  try {
    // 拉取项目
    spinner.start();
    await new Promise((resolve, reject) => {
      download(gitPath, projectName, { clone: true }, (err) => {
        if (err) reject({ errorReason: err, errorType: typeData.create });
        resolve();
      });
    });
    spinner.succeed("项目创建成功~");
    // 适配 window平台为npm.cmd
    const commandName = process.platform === "win32" ? "npm.cmd" : "npm";
    // install项目
    installModules.start();
    await execCommand(
      `${commandName} install`,
      {
        cwd: `./${projectName}`,
      },
      typeData.install
    );
    installModules.succeed("node_modules安装成功~");
    // run 项目
    console.log(" 项目启动中...");
    await execCommand(
      `${commandName} run dev`,
      { cwd: `./${projectName}` },
      typeData.run
    );
  } catch (error) {
    if (error.errorReason) {
      const { errorReason, errorType } = error;
      const { type, desc } = errorType;
      if (type === "spinner") {
        spinner.fail(desc + "失败：" + errorReason);
      } else if (type === "installModules") {
        installModules.fail(desc + "失败：" + errorReason);
      } else if (type === "runProject") {
        console.log(desc + "失败：" + errorReason);
      }
    } else {
      console.log(error);
    }
  }
};

// 监听输入的命令
program
  .command("create <project-name>")
  .description("创建项目")
  .action(function (projectName) {
    inquirer
      .prompt([
        {
          type: "input", // 类型有很多，如confirm确认 list选择 checkbox多选
          name: "projectName",
          message: "请输入项目名称",
          default: projectName,
          validate: (input) => {
            return input ? true : "项目名称不能为空";
          },
        },
        {
          type: "confirm",
          name: "isTs",
          message: "是否使用ts",
          default: false,
        },
      ])
      .then((result) => {
        const { projectName, isTs } = result;
        if (isExist(`./${projectName}`)) {
          console.log("项目已存在");
          return;
        }
        if (isTs) {
          console.log("暂无ts支持");
        }
        createProjectAction(projectName, isTs);
      })
      .catch((err) => {});
  });
program.parse(process.argv);
